package util;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import dao.ClienteDAO;
import dao.CotizacionDAO;
import dao.ListaPreciosDAO;

import bean.*;

/**
 * Esta clase sirve para leer archivos XMLs. 
 * @author nicolasmondada
 * @author lcouget
 */
public class XmlReader 
{
	/**
	 * recibe una lista de precios obtenida en el path y la persiste en el sistema.
	 * @author lcouget
	 * @param 
	 * @param Path donde obtiene la lista de precios.
	 * @return ListaPrecios Objeto tipo ListaPrecios con los valores leidos del XML.
	 */
	public boolean leerListaPrecios(String path)
	{
		ListaPrecios lp = new ListaPrecios();
		try
		{
			//armo el document para leer el xml
			File F_ListaPrecios = new File( path );
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			Document doc = dBuilder.parse(F_ListaPrecios);
			doc.getDocumentElement().normalize();
			
			//Nodos de Proveedor
			NodeList nodosProveedor = doc.getElementsByTagName("Proveedor");
			Node nodoProveedor = nodosProveedor.item(0);

			if (nodoProveedor.getNodeType() == Node.ELEMENT_NODE) 
			{
				Element element = (Element) nodoProveedor;

				if( getValue("Cuil", element) != "")
				{
					//seteo los datos del proveedor
					Proveedor p = new Proveedor();
					p.setCUIT(getValue("Cuil", element));
					p.setRazonSocial(getValue("RazonSocial", element));
					lp.setProveedor(p);
				}
				else
				{
					System.out.println("No se pudo leer los datos del proveedor");
				}

			}
			
			//Nodo de Vigencia
			NodeList nodosVigencia = doc.getElementsByTagName("Vigencia");
			Node nodoVigencia = nodosVigencia.item(0);

			if (nodoVigencia.getNodeType() == Node.ELEMENT_NODE) 
			{
				Element element = (Element) nodoVigencia;
				if( getValue("Fecha", element) != "" && getValue("Termino", element) != "")
				{	
					//calculo la fecha de vencimiento
					SimpleDateFormat f = new SimpleDateFormat("dd/mm/yyyy"); //ToDo: ver si el formato de fecha es este o cambia.
					Date fechaPublicacionDate = f.parse(getValue("Fecha", element));
					Date fechaVencimientoDate = this.addDays(fechaPublicacionDate, Integer.parseInt(getValue("Termino", element)));
					
					//seteo la fecha de vencimiento en la lista de precios
					lp.setFechaVencimiento(fechaVencimientoDate);
				}
				else
				{
					System.out.println("No se pudo leer la fecha de vencimiento");
				}
			}
						
			//nodos de <CondicionesDeVenta>
			//<PagoContado>
			NodeList nodosPagoContado = doc.getElementsByTagName("PagoContado");
			
			List<CondicionVenta> cv = null;
			
			Node nodoPagoContado = nodosPagoContado.item(0);

			if (nodoPagoContado.getNodeType() == Node.ELEMENT_NODE) 
			{
				Element element = (Element) nodoPagoContado;
				CondicionVenta cvContado = new CondicionVenta();
				cvContado.setDescuento(Float.parseFloat(getValue("Descuento", element)));
				cvContado.setTipo("contado");
				
				cv.add(cvContado);
			}

			//<Financiacion>
			NodeList nodosFinanciacion = doc.getElementsByTagName("Financiacion");

			for (int i = 0; i < nodosFinanciacion.getLength(); i++) 
			{
				Node nodoFinanciacion = nodosFinanciacion.item(i);

				if (nodoFinanciacion.getNodeType() == Node.ELEMENT_NODE) 
				{
					Element element = (Element) nodoFinanciacion;
					
					CondicionVenta cvFinanciado = new CondicionVenta();
					cvFinanciado.setRecargo(Float.parseFloat(getValue("Descuento", element)));
					cvFinanciado.setDiasFinanciacion(Integer.parseInt(element.getAttribute("dias")));
					cvFinanciado.setTipo("financiacion");
					
					cv.add(cvFinanciado);
				}
			}
			
			//agrego las condiciones de venta a la lista de precios
			lp.setCondicionesDeVenta(cv);
			
			//Nodos de Rodamientos
			//<item>
			NodeList nodosRodamientos = doc.getElementsByTagName("Item");
			List<ItemListaPrecios> items = null;
			
			for (int i = 0; i < nodosRodamientos.getLength(); i++) 
			{
				Node nodoRodamiento = nodosRodamientos.item(i);

				if (nodoRodamiento.getNodeType() == Node.ELEMENT_NODE) 
				{
					Element element = (Element) nodoRodamiento;

					//cargo el rodamiento
					Rodamiento r = new Rodamiento();
					r.setCodigoSkf(getValue("Sufijo", element));
					r.setMarca(getValue("Marca", element));
					r.setOrigen(getValue("Origen", element));
					
					//cargo el itemListaPrecio
					ItemListaPrecios ilp = new ItemListaPrecios();
					ilp.setNroSerie(element.getAttribute("serie"));
					ilp.setPrecio(Float.parseFloat(getValue("Precio", element)));
					ilp.setRodamiento(r);
					
					//agrego el item al list de items
					items.add(ilp);
				}
			}
			//agrego la lista de items a la lista de precios.
			lp.setItems(items);
			
			//Nodos de Reemplazo
			NodeList nodosReemplaza = doc.getElementsByTagName("ListaReemplazada");
			
			Node nodoReemplaza = nodosReemplaza.item(0);

			if (nodoReemplaza.getNodeType() == Node.ELEMENT_NODE) 
			{
				Element element = (Element) nodoReemplaza;
				
				String tipo =  element.getAttribute("tipo");
				String numero =  element.getAttribute("numero");
				
				ListaPreciosDAO lpd = ListaPreciosDAO.getInstancia();
				if( numero != "1") //hay lista para reemplazar
				{
					//busco la lista de precios a reemplazar
					ListaPrecios lpAnterior = lpd.obtenerListaPrecios(lp.getProveedor(), tipo);
					
					//chequeo que no haya una lista anterior con fecha de vencimiento CHEQUEAR ESTO
					if(lpAnterior.getFechaVencimiento().after(lp.getFechaVencimiento()) )
					{
						System.out.println("Hay una lista de precios anterior que no vencio");
					}
					else
					{
						//guardo la Lista de Precios
						lpd.guardarListaPrecios(lp);
					}
				}
				else
				{
					//Es la Primer Lista de Precios. Guardo la Lista directamente.
					lpd.guardarListaPrecios(lp);
				}
			}
		}
		catch (Exception ex) 
		{
			ex.printStackTrace();
			return false;
		}
		return true;	
	}
	
	/**
	 * Metodo encargado de leer un archivo XML de solicitud de cotizacion y devolver los datos cargados 
	 * en una instancia de SolicitudCotizacion
	 * @param path el path del archivo a leer
	 * @return instancia de SolicitudCotizacion con los datos obtenidos.
	 */
	
	public SolicitudCotizacion leerSolicitudCotizacion( String path )
	{	
		//genero una instancia de Solicitud de Cotizacion
		SolicitudCotizacion sc = new SolicitudCotizacion();
		
		try
		{	
			//armo el document para leer el xml
			File F_SolCot = new File( path );
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			Document doc = dBuilder.parse(F_SolCot);
			doc.getDocumentElement().normalize();
			
			//obtengo el numero de solicitud y la fecha.
			String nroSolCotizacion = doc.getDocumentElement().getAttribute("numero");
			String fechaSolicitud = doc.getDocumentElement().getAttribute("fecha");
			
			//seteo la fecha de solicitud y el cliente
			SimpleDateFormat f = new SimpleDateFormat("dd/mm/yyyy"); //ToDo: ver si el formato de fecha es este o cambia.
			Date fechaSolCotDate = f.parse(fechaSolicitud);
			sc.setFechaSolicitud(fechaSolCotDate);
				
			//Nodo <Cliente>
			NodeList nodosCliente = doc.getElementsByTagName("Cliente");
			Node nodoCliente = nodosCliente.item(0);

			if (nodoCliente.getNodeType() == Node.ELEMENT_NODE) 
			{
				Element element = (Element) nodoCliente;

				if( getValue("Cuil", element) != "")
				{
					ClienteDAO cd = ClienteDAO.getInstancia();
					Cliente c = cd.obtenerClientePorCUIT( getValue("Cuil", element) );
					
					//seteo los datos del cliente FALTA VERIFICACION
					sc.setCliente(c);
				}
				else
				{
					System.out.println("No se pudo leer los datos cliente");
				}

			}
			
			//Nodos de Rodamientos
			//<item>
			NodeList nodosRodamientos = doc.getElementsByTagName("Item");
			List<ItemSolicitudCotizacion> items = null;
			
			for (int i = 0; i < nodosRodamientos.getLength(); i++) 
			{
				Node nodoRodamiento = nodosRodamientos.item(i);

				if (nodoRodamiento.getNodeType() == Node.ELEMENT_NODE) 
				{
					Element element = (Element) nodoRodamiento;

					//cargo el rodamiento
					Rodamiento r = new Rodamiento();
					r.setCodigoSkf(getValue("Sufijo", element));
					r.setMarca(getValue("Marca", element));
					r.setOrigen(getValue("Origen", element));
					
					//cargo el itemSolicitudCotizacion
					ItemSolicitudCotizacion isc = new ItemSolicitudCotizacion();
					isc.setCantidad(Integer.parseInt(getValue("Cantidad", element)));
					isc.setRodamiento(r);
					
					//agrego el item al list de items
					items.add(isc);
				}
			}
			//agrego la lista de items a la sol. de Cotizacion.
			sc.setItems(items);	
		}
		catch (Exception ex) 
		{
			ex.printStackTrace();
		}
		return sc;	
	}
	
	/**
	 * Metodo encargado de leer un XML de pedidoVenta y pasar todos sus datos a un objeto tipo PedidoVenta
	 * @param path El path donde lee el XML
	 * @return instancia de PedidoVenta con sus respectivos datos.
	 */
	
	public PedidoVenta leerPedidoVenta( String path )
	{
		PedidoVenta pv = new PedidoVenta();
		
		try
		{	
			//armo el document para leer el xml
			File F_PedidoVenta = new File( path );
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			Document doc = dBuilder.parse(F_PedidoVenta);
			doc.getDocumentElement().normalize();
			
			//obtengo el numero de solicitud y la fecha.
			String nroPedVenta = doc.getDocumentElement().getAttribute("numero");
			
			//Nodo <Fecha>
			NodeList nodosFecha = doc.getElementsByTagName("Fecha");
			Node nodoFecha = nodosFecha.item(0);

			if (nodoFecha.getNodeType() == Node.ELEMENT_NODE) 
			{
				Element element = (Element) nodoFecha;
			
				//seteo la fecha de la orden de pedido
				SimpleDateFormat f = new SimpleDateFormat("dd/mm/yyyy"); //ToDo: ver si el formato de fecha es este o cambia.
				Date fechaPVDate = f.parse(getValue("Fecha", element));
				pv.setFecha(fechaPVDate);
			}
			
			//Nodo <Cliente>
			NodeList nodosCliente = doc.getElementsByTagName("Cliente");
			Node nodoCliente = nodosCliente.item(0);

			if (nodoCliente.getNodeType() == Node.ELEMENT_NODE) 
			{
				Element element = (Element) nodoCliente;

				if( getValue("Cuil", element) != "")
				{
					ClienteDAO cd = ClienteDAO.getInstancia();
					Cliente c = cd.obtenerClientePorCUIT( getValue("Cuil", element) );
					
					//seteo los datos del cliente FALTA VERIFICACION
					pv.setCliente(c);
				}
				else
				{
					System.out.println("No se pudo leer los datos cliente");
				}
			}
			
			//nodo <cotizacion>
			NodeList nodosNumeroCot = doc.getElementsByTagName("NumeroCotizacion");
			Node nodoNumeroCot = nodosNumeroCot.item(0);
	
			if (nodoNumeroCot.getNodeType() == Node.ELEMENT_NODE) 
			{
				Element element = (Element) nodoNumeroCot;

				if( getValue("NumeroCotizacion", element) != "")
				{
					CotizacionDAO cd = CotizacionDAO.getInstancia();
					Cotizacion cot = cd.obtenerCotizacionPorNumero( Integer.parseInt( getValue("NumeroCotizacion", element) ) );
					pv.setCotizacion(cot);
				}
				else
				{
					System.out.println("No se pudo leer el numero de cotizacion");
				}
			}
			
			//nodos de <CondicionesDeVenta>
			//<PagoContado>
			NodeList nodosPagoContado = doc.getElementsByTagName("PagoContado");
			
			List<CondicionVenta> cv = null;
			
			Node nodoPagoContado = nodosPagoContado.item(0);

			if (nodoPagoContado.getNodeType() == Node.ELEMENT_NODE) 
			{
				Element element = (Element) nodoPagoContado;
				CondicionVenta cvContado = new CondicionVenta();
				cvContado.setDescuento(Float.parseFloat(getValue("Descuento", element)));
				cvContado.setTipo("contado");
				
				cv.add(cvContado);
			}

			//<Financiacion>
			NodeList nodosFinanciacion = doc.getElementsByTagName("Financiacion");

			for (int i = 0; i < nodosFinanciacion.getLength(); i++) 
			{
				Node nodoFinanciacion = nodosFinanciacion.item(i);

				if (nodoFinanciacion.getNodeType() == Node.ELEMENT_NODE) 
				{
					Element element = (Element) nodoFinanciacion;
					
					CondicionVenta cvFinanciado = new CondicionVenta();
					cvFinanciado.setRecargo(Float.parseFloat(getValue("Descuento", element)));
					cvFinanciado.setDiasFinanciacion(Integer.parseInt(element.getAttribute("dias")));
					cvFinanciado.setTipo("financiacion");
					
					cv.add(cvFinanciado);
				}
			}
			//agrego las condiciones de venta a la lista de precios
			pv.setCondicionesVenta(cv);
			
			//Nodos de Rodamientos
			//<item>
			NodeList nodosRodamientos = doc.getElementsByTagName("Item");
			List<ItemPedidoVenta> items = null;
			
			for (int i = 0; i < nodosRodamientos.getLength(); i++) 
			{
				Node nodoRodamiento = nodosRodamientos.item(i);

				if (nodoRodamiento.getNodeType() == Node.ELEMENT_NODE) 
				{
					Element element = (Element) nodoRodamiento;

					//cargo el rodamiento
					Rodamiento r = new Rodamiento();
					r.setCodigoSkf(getValue("Sufijo", element));
					r.setMarca(getValue("Marca", element));
					r.setOrigen(getValue("Origen", element));
					
					//cargo el itemPedidoVenta
					ItemPedidoVenta ipv = new ItemPedidoVenta();
					ipv.setCantidad(Integer.parseInt(getValue("Cantidad", element)));
					ipv.setRodamiento(r);
					
					//agrego el item al list de items
					items.add(ipv);
				}
			}
			//agrego la lista de items a la sol. de Cotizacion.
			pv.setItems(items);
			
		}
		catch (Exception ex) 
		{
			ex.printStackTrace();
		}	
		return pv;
	}
	
	/**
	 * Metodo que se encarga de obtener valor de un tag especifico XML
	 * @param tag
	 * @param element
	 * @return Valor del Nodo
	 */
	private static String getValue(String tag, Element element) 
	{
		NodeList nodes = element.getElementsByTagName(tag).item(0).getChildNodes();
		Node node = (Node) nodes.item(0);
		return node.getNodeValue();
	}
	
	/**
	 * Metodo que sirve para agregar dias a la fecha Date
	 * @param date
	 * @param days
	 * @return
	 */
	public Date addDays(Date date, int days)
    {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, days); //minus number would decrement the days
        return cal.getTime();
    }
}

